<template>
  <!--Dialog-->
  <Dialog v-model="modelValue">
    <el-form :status-icon="true" :inline="true" :model="updateForm" label-width="auto" ref="updateFormRef">
      <el-row>
        <el-col :span="24">
          <el-form-item label="名称" prop="name" :rules="[{ required: true, message: '请输入角色名称' }]">
            <el-input v-model="updateForm.name" placeholder="请输入角色名称" maxlength="256" />
          </el-form-item>
          <el-form-item label="是否公开" prop="isPublic" :rules="[{ required: true, message: '请选择是否默认' }]">
            <el-switch v-model="updateForm.isPublic" />
          </el-form-item>
          <el-form-item label="是否默认" prop="isDefault" :rules="[{ required: true, message: '请选择是否默认' }]">
            <el-switch v-model="updateForm.isDefault" /> </el-form-item></el-col>
        <el-col :span="24">
          <el-form-item label="角色权限" :rules="[{ required: true, message: '请选择角色权限' }]">
            <el-tree class="el-tree" :data="trees" :render-content="renderContent" :show-checkbox="true" node-key="id"
              ref="treeRef" :highlight-current="true" @node-expand="handleExpand" :props="defaultProps"></el-tree>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="数据权限" prop="DataPermission" :rules="[{ required: true, message: '请选择数据权限' }]">
            <el-select v-model="updateForm.DataPermission" @change="dropDataPermission" clearable placeholder="请选择数据权限"
              style="width: 260px">
              <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item label="自定义权限" v-if="updateForm.DataPermission === DataPermission.Custom">
            <OrganizationSelect v-model="updateForm.CustomDataPermission" @change="onsetSelectedNode"
              :keyType="1"
              placeholder="请选择所属组织" :props="customDataPermissionProps" style="width: 256px" />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <el-button type="primary" @click="onSavue(updateFormRef)" :loading="isLoading">保存</el-button>
      <el-button @click="onClose">关闭</el-button>
    </template>
  </Dialog>
</template>

<script setup lang="ts">
import { OrganizationSelect } from '@/views/base/organization/select/index';
import { reqPermissionAll } from '@/utils/api/permission/index';
import { getAsync, updateAsync, getPermissionListAsync } from '@/utils/api/role/index';
import { Dialog } from '@/components/dialog/index';
import { propTypes } from '@/utils/propTypes';
import { onMounted, ref, nextTick } from 'vue';
import { ElMessage } from 'element-plus';
import type { ElTree, FormInstance } from 'element-plus';
import type { UpdatePermissionDto } from '@/utils/api/role/type';
import type { ValidateFieldsError } from 'async-validator/dist-types';
import { PermissionType, type PermissionTreeDto } from '@/utils/api/permission/type';
import { differ } from '@/utils/enumerable';
import { createRoleUpdateDto, createRoleUpdateView, type RoleUpdateView } from '../../types';
import { DataPermission } from '@/utils/api/type';

// 选项数据
const options = [
  {
    value: 0,
    label: '全部数据权限',
  },
  {
    value: 1,
    label: '本门组织',
  },
  {
    value: 2,
    label: '下级组织数据权限',
  },
  {
    value: 3,
    label: '本组织及下级组织数据权限',
  },
  {
    value: 4,
    label: '自定义',
  }
];

const customDataPermissionProps = {
  multiple: true,
  checkStrictly: true,
};

const props = defineProps({
  id: propTypes.string
});

// 选择数据权限
const dropDataPermission = (val: DataPermission) => {
  if (val !== DataPermission.Custom) {
    clearCustomDataPermission();
  }
};

// 清空数据
const clearCustomDataPermission = () => {
  updateForm.value.CustomDataPermission = [];
};

// 组织选择后的业务逻辑
const onsetSelectedNode = (val: any) => {
  const array = [];
  if (val) {
    for (let i = 0; i < val.length; i++) {
      array.push(val[i][val[i].length - 1]);
    }
  }
  updateForm.value.CustomDataPermission = array;
};

let $emit = defineEmits(['update:refresh']);
// 刷新
const refresh = async () => {
  // 通知页面重新加载
  $emit('update:refresh');
};

// 控制组件隐藏与显示
const modelValue = defineModel<boolean>(propTypes.bool.def(false));
const close = () => {
  modelValue.value = false;
};
// 保存Loading效果状态
const isLoading = ref<boolean>(false);

// tree组件实例对象
const treeRef = ref<InstanceType<typeof ElTree>>();

//组件挂载完毕
onMounted(async () => {
  // 加载权限
  await initAllPermissionAsync();

  // 加载角色权限
  await initRolePermission();

  // 更改tree按钮横向样式
  changeCss();

  // 根据id绑定角色数据
  await initRoleAsync();

  // 记录之前的选中数据
  initDefaultCheckedkeys();
});

// 权限PermissionTreeDt转化成Tree数组
const getSeletcPermission = (permissions: Array<PermissionTreeDto>): Array<Tree> => {
  let arrays = new Array<Tree>();
  permissions.forEach((item) => {
    let tree: Tree = {
      id: item.name,
      label: item.displayName!,
      isFloat: item.type == PermissionType.Button
    };
    if (item.childPermissions && item.childPermissions.length > 0) {
      tree.children = getSeletcPermission(item.childPermissions);
    }
    arrays.push(tree);
  });
  return arrays;
};

// 加载角色信息
const initRoleAsync = async () => {
  updateForm.value = createRoleUpdateView(await getAsync(props.id));
};

// 加载角色权限
const beforePermissions: Array<string> = [];
const initRolePermission = async () => {
  // 设置节点选中
  const checkedkeys = await getPermissionListAsync(props.id);
  for (let index = 0; index < checkedkeys.length; index++) {
    const item = checkedkeys[index];
    treeRef.value!.setChecked(item, true, false);
  }
};

// 加载操作前选中数据
const initDefaultCheckedkeys = () => {
  const checkedNodes = treeRef.value!.getCheckedNodes(false, true);
  for (let index = 0; index < checkedNodes.length; index++) {
    const item = checkedNodes[index];
    beforePermissions.push(item.id);
  }
};

// 加载权限
const initAllPermissionAsync = async () => {
  const data = await reqPermissionAll();
  const treeData = getSeletcPermission(data);
  trees.value = treeData;
};

// 根据角色加载权限

// 关闭
const onClose = () => {
  //触发自定义事件
  close();
};

// 保存
const onSavue = async (formEl: FormInstance | undefined): Promise<void> => {
  if (!formEl) {
    return;
  }

  // 提交验证
  await formEl.validate(
    async (isValid: boolean, invalidFields?: ValidateFieldsError): Promise<void> => {
      if (isValid) {
        try {
          isLoading.value = true;
          // 选中的的数据
          const checkedNodes = treeRef.value!.getCheckedNodes(false, true);
          let permissions = new Array<UpdatePermissionDto>();
          for (let index = 0; index < checkedNodes.length; index++) {
            const item = checkedNodes[index];
            permissions.push({ name: item.id, isGranted: true });
          }
          if (permissions.length <= 0) {
            ElMessage({
              showClose: true,
              message: '请选择角色权限',
              type: 'error'
            });
            return;
          }

          let afterPermissions = permissions.map((item) => item.name);
          const differResult = differ(beforePermissions, afterPermissions);
          let result = new Array<UpdatePermissionDto>();
          differResult.after.forEach((item) => {
            result.push({ name: item, isGranted: true });
          });
          differResult.before.forEach((item) => {
            result.push({ name: item, isGranted: false });
          });

          updateForm.value.permissions = result;
          await updateAsync(updateForm.value.id, createRoleUpdateDto(updateForm.value));
          // 关闭弹窗
          close();
          // 提示成功
          ElMessage({
            showClose: true,
            message: '修改成功',
            type: 'success'
          });
          // 刷新父组件
          refresh();
        } catch (error) {
          if (error) {
            let msg: string = (error as Error).message;
            if (msg) {
              ElMessage({
                showClose: true,
                message: (error as Error).message,
                type: 'error'
              });
            }
          }
        } finally {
          isLoading.value = false;
        }
      } else {
        console.log('error submit!', invalidFields);
      }
    }
  );
};

// 组件实例
const updateFormRef = ref<FormInstance>();
// 角色对象
const updateForm = ref<RoleUpdateView>({
  id: '',
  name: '',
  isPublic: false,
  isDefault: false,
  isStatic: false,
  CustomDataPermission: [],
  DataPermission: DataPermission.All,
  permissions: []
});

// 数据对象
const defaultProps = {
  children: 'children',
  label: 'label'
};

// Tree
interface Tree {
  id: string;
  label: string;
  isFloat?: boolean;
  children?: Tree[];
}

// 权限数据
const trees = ref<Array<Tree>>([]);

// 更新树的css
const changeCss = () => {
  let levelNames = document.getElementsByClassName('foo'); // levelname是上面的最底层节点的名字
  for (let i = 0; i < levelNames.length; i++) {
    // cssFloat 兼容 ie6-8  styleFloat 兼容ie9及标准浏览器
    let levelName = levelNames[i].parentNode?.parentNode as HTMLElement;
    levelName.style.cssFloat = 'left'; // 最底层的节点，包括多选框和名字都让他左浮动
    //levelName.style.width = '240px'
  }
};

// tree renderContent
const renderContent = (
  h: any,
  {
    data
  }: {
    data: Tree;
  }
) => {
  //树节点的内容区的渲染 Function
  let classname = '';
  // 由于项目中有三级菜单也有四级级菜单，就要在此做出判断
  if (data.isFloat) {
    classname = 'foo';
  }
  return h(
    'div',
    {
      class: classname
    },
    data.label
  );
};

// 节点被展开时触发的事件
const handleExpand = () => {
  //节点被展开时触发的事件
  //因为该函数执行在renderContent函数之前，所以得加this.$nextTick()
  nextTick(() => {
    changeCss();
  });
};
</script>
<style scoped lang="scss"></style>
